/*
 * Copyright 2016-2017 lei.xu<xulei2008xulei@163.com>.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.san21go.jfinfunc;

import org.san21go.jfinfunc.financ.irr.IRR;
import org.san21go.jfinfunc.financ.norm.Alpha;
import org.san21go.jfinfunc.financ.norm.Beta;
import org.san21go.jfinfunc.financ.norm.InformationRatio;
import org.san21go.jfinfunc.financ.norm.MaxDrawdown;
import org.san21go.jfinfunc.financ.norm.MaxDrawdownRatio;
import org.san21go.jfinfunc.financ.norm.Sharpe;
import org.san21go.jfinfunc.financ.norm.Treynor;
import org.san21go.jfinfunc.financ.npv.NPV;
import org.san21go.jfinfunc.financ.xirr.XIRR;
import org.san21go.jfinfunc.financ.xirr.XNPV;
import org.san21go.jfinfunc.jfinfunc.math.CORREL;
import org.san21go.jfinfunc.math.covariance.COVARIANCEP;
import org.san21go.jfinfunc.math.covariance.COVARIANCES;
import org.san21go.jfinfunc.math.stdev.STDEVP;
import org.san21go.jfinfunc.math.stdev.STDEVS;
import org.san21go.jfinfunc.math.var.VARP;
import org.san21go.jfinfunc.math.var.VARS;
import org.san21go.jfinfunc.time.YEARFRAC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description: 金融函数工具类
 *
 * @version V1.0
 */
public class FinFuncUtils {
	public static final String HUNDSUN_VERSION = "@system 理财资产管理系统V2.2 @version v2.2.0.1 @lastModiDate 2016年6月7日 @describe  ";
	public static final Logger logger = LoggerFactory.getLogger(FinFuncUtils.class);

	/**
	 * 返回 start_date 和 end_date 之间的天数占全年天数的百分比。 使用 YEARFRAC
	 * 工作表函数可判别某一特定条件下全年效益或债务的比例。
	 * 
	 * @return
	 * @author xulei
	 */
	public static double YEARFRAC(String startDate, String endDate, String basis) {
		YEARFRAC yearfrac = new YEARFRAC(startDate, endDate, basis);
		return yearfrac.evaluate();
	}

	/**
	 * NPV 函数 使用贴现率和一系列未来支出（负值）和收益（正值）来计算一项投资的净现值。
	 * 
	 * @param values
	 * @param rate
	 * @return
	 */
	public static double NPV(double[] values, double rate) {
		NPV npv = new NPV(values, rate);
		return npv.evaluate();
	}

	/**
	 * IRR 函数 返回由值中的数字表示的一系列现金流的内部收益率。 这些现金流不必等同，因为它们可能作为年金。
	 * 但是，现金流必须定期（如每月或每年）出现。 内部收益率是针对包含付款（负值）和收入（正值）的定期投资收到的利率。
	 * 
	 * @param values
	 *            用来计算内部收益率的数字
	 * @param guess
	 *            对函数 IRR 计算结果的估计值。
	 * @return
	 */
	public static double IRR(double[] values, double guess) {
		IRR irr = new IRR(values, guess);
		return irr.evaluate();
	}

	/**
	 * 返回一组不一定定期发生的现金流的内部收益率。
	 * 
	 * @param amounts
	 *            发生额
	 * @param dates
	 *            日期
	 * @param guess
	 *            预测值
	 * @return
	 */
	public static double XIRR(double[] amounts, String[] dates, double guess) {
		XIRR xirr = new XIRR(amounts, dates, guess);
		return xirr.evaluate();
	}

	/**
	 * 返回一组现金流的净现值，这些现金流不一定定期发生。
	 * 
	 * @param rate
	 * @param amounts
	 * @param dates
	 * @return
	 */
	public static double XNPV(double rate, double[] amounts, String[] dates) {
		XNPV xnpv = new XNPV(rate, amounts, dates);
		return xnpv.evaluate();
	}

	/**
	 * STDEV.P 函数 基于样本估算标准偏差（忽略样本中的逻辑值和文本）。
	 * 
	 * @param values
	 * @return
	 */
	public static double STDEVP(double[] values) {
		STDEVP stdevp = new STDEVP(values);
		return stdevp.evaluate();
	}

	/**
	 * STDEV.S 函数 计算基于以参数形式给出的整个样本总体的标准偏差（忽略逻辑值和文本）。
	 * 
	 * @param values
	 * @return
	 */
	public static double STDEVS(double[] values) {
		STDEVS stdevs = new STDEVS(values);
		return stdevs.evaluate();
	}

	/**
	 * COVARIANCES.P 函数 <br/>
	 * 返回总体协方差，即两个数据集中每对数据点的偏差乘积的平均数。
	 * 
	 * @param values
	 * @return
	 */
	public static double COVARIANCEP(double[] value1s, double[] value2s) {
		COVARIANCEP covariancep = new COVARIANCEP(value1s, value2s);
		return covariancep.evaluate();
	}

	/**
	 * COVARIANCES.S 函数 <br/>
	 * 返回样本协方差，即两个数据集中每对数据点的偏差乘积的平均数。
	 * 
	 * @param values
	 * @return
	 */
	public static double COVARIANCES(double[] value1s, double[] value2s) {
		COVARIANCES covariances = new COVARIANCES(value1s, value2s);
		return covariances.evaluate();
	}

	/**
	 * CORREL 函数 <br/>
	 * 使用相关系数确定两个属性之间的关系。
	 * 
	 * @param values
	 * @return
	 */
	public static double CORREL(double[] value1s, double[] value2s) {
		CORREL correl = new CORREL(value1s, value2s);
		return correl.evaluate();
	}

	/**
	 * VAR.S 函数 <br/>
	 * 估算基于样本的方差
	 * 
	 * @param values
	 * @return
	 */
	public static double VARS(double[] values) {
		VARS vars = new VARS(values);
		return vars.evaluate();
	}

	/**
	 * VAR.P 函数 <br/>
	 * 估算基于总体的方差
	 * 
	 * @param values
	 * @return
	 */
	public static double VARP(double[] values) {
		VARP varp = new VARP(values);
		return varp.evaluate();
	}

	/**
	 * 最大回撤率
	 * 
	 * @param pValues
	 * @param pDates
	 * @return
	 */
	public static double maxDrawdownRatio(double[] pValues, String[] pDates) {
		MaxDrawdownRatio mddr = new MaxDrawdownRatio(pValues, pDates);
		return mddr.evaluate();
	}

	/**
	 * 最大回撤
	 * 
	 * @param pValues
	 * @param pDates
	 * @return
	 */
	public static double maxDrawdown(double[] pValues, String[] pDates) {
		MaxDrawdown mdd = new MaxDrawdown(pValues, pDates);
		return mdd.evaluate();
	}

	/**
	 * Alpha系数又称简森指数/詹森指数(Jensen)<br/>
	 * 
	 * @param yieldRates
	 *            年化收益率
	 * @param baseRates
	 *            基准收益率
	 * @param freeRiskRates
	 *            无风险收益率
	 * @return
	 */
	public static double alpha(double[] yieldRates, double[] baseRates, double[] freeRiskRates) {
		Alpha alpha = new Alpha(yieldRates, baseRates, freeRiskRates);
		return alpha.evaluate();
	}

	/**
	 * Beta值
	 * 
	 * @param yieldRates
	 *            年化收益率
	 * @param baseRates
	 *            基准收益率
	 * @return
	 */
	public static double beta(double[] yieldRates, double[] baseRates) {
		Beta beta = new Beta(yieldRates, baseRates);
		return beta.evaluate();
	}

	/**
	 * Information Ratio 信息比率
	 * 
	 * @param yieldRates
	 *            年化收益率
	 * @param baseRates
	 *            基准收益率
	 * @return
	 */
	public static double informationRatio(double[] yieldRates, double[] baseRates) {
		InformationRatio imr = new InformationRatio(yieldRates, baseRates);
		return imr.evaluate();
	}

	/**
	 * SharpeRatio 夏普比率
	 * 
	 * @param yieldRates
	 *            年化收益率
	 * @param dates
	 *            日期
	 * @param freeRiskRates
	 *            无风险收益率
	 * @return
	 */
	public static double sharpe(double[] yieldRates, String[] dates, double[] freeRiskRates) {
		Sharpe sr = new Sharpe(yieldRates, dates, freeRiskRates);
		return sr.evaluate();
	}

	/***
	 * 特雷诺指数（Treynor）
	 * 
	 * @param yieldRates
	 *            年化收益率
	 * @param baseRates
	 *            基准收益率
	 * @param freeRiskRates
	 *            无风险收益率
	 * @return
	 */
	public static double treynor(double[] yieldRates, double[] baseRates, double[] freeRiskRates) {
		Treynor treynor = new Treynor(yieldRates, baseRates, freeRiskRates);
		return treynor.evaluate();
	}

}
